﻿//#define TRACE_1
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ProjectEulerSolutions.Problems
{
    /*
     * A hexagonal tile with number 1 is surrounded by a ring of six hexagonal tiles, starting at "12 o'clock" and numbering the tiles 2 to 7 in an anti-clockwise direction.

New rings are added in the same fashion, with the next rings being numbered 8 to 19, 20 to 37, 38 to 61, and so on. The diagram below shows the first three rings.

By finding the difference between tile n and each its six neighbours we shall define PD(n) to be the number of those differences which are prime.

For example, working clockwise around tile 8 the differences are 12, 29, 11, 6, 1, and 13. So PD(8) = 3.

In the same way, the differences around tile 17 are 1, 17, 16, 1, 11, and 10, hence PD(17) = 2.

It can be shown that the maximum value of PD(n) is 3.

If all of the tiles for which PD(n) = 3 are listed in ascending order to form a sequence, the 10th tile would be 271.

Find the 2000th tile in this sequence.

     * */
    class Problem128 : IProblem
    {
        public string Calculate()
        {
            int target = 2000;
            int count = 1; //broj jedan je prvi
            int layer = 0;
            int[] thisLayer = new int[2];
            int[] nextLayer = new int[2];

            SieveOfAtkin sieve = new SieveOfAtkin(1500000);

            while (true)
            {
                layer++;
                int secondNext = 6 * layer + 1;
                int lastThis = secondNext - 2; //6*layer - 1
                int lastNext = 6 * (layer + 1) + 6 * layer - 1;
                int secondLastNext = lastNext -  6 * layer;

                if (sieve.IsPrime(secondNext))
                    thisLayer[0]++;
                if (sieve.IsPrime(lastThis))
                {
                    thisLayer[0]++;
                    thisLayer[1]++;
                }
                if (sieve.IsPrime(lastNext))
                {
                    thisLayer[0]++;
                    nextLayer[1]++;
                }
                if (sieve.IsPrime(secondLastNext))
                    thisLayer[1]++;

                if (thisLayer[0] == 3)
                {
                    count++;
                    //Console.WriteLine(6 * CommonFunctions.CalculateBinomeBig(layer, 2) + 2);
                    if (count == target)
                    {
                        return (6 * CommonFunctions.CalculateBinomeBig(layer, 2) + 2).ToString();
                    }
                }

                if (thisLayer[1] == 3)
                {
                    count++;
                    //Console.WriteLine(6 * CommonFunctions.CalculateBinomeBig(layer, 2) + 2);
                    if (count == target)
                    {
                        return (6 * CommonFunctions.CalculateBinomeBig(layer + 1, 2) + 1).ToString();
                    }
                }

                thisLayer = nextLayer;
                nextLayer = new int[2];
            }
        }
    }
}
